#include "Level.h"
#include "ImgMgr.h"
#include "Player.h"
#include "Ball.h"
#include "Tile.h"
#include "Mob.h"
#include "RegenTile.h"
#include "FleshTile.h"
#include "LadderTile.h"
#include "PortalTile.h"
#include "InfectedFleshTile.h"
#include "PikeMob.h"
#include "BacteriaMob.h"

Level::Level()
{

}

Level::~Level()
{
    int e;
    int u;
    int i;
    unsigned x;
    for(e = 0; e <3; e++)
	{
		for(u = 0; u < 40; u++)
		{
			for(i = 0; i < 128; i++)
			{
				delete m_tile[e][u][i];
			}
		}
	}
	for(x = 0; x < m_ball.size(); x++)
	{
	    delete m_ball[x];
	}
	for(x = 0; x < m_mob.size(); x++)
	{
	    delete m_mob[x];
	}
}

void Level::init(ImgMgr *imageManager)
{
	int e;
	int u;
	int i;
	m_imageManager = imageManager;
	m_currentLevel = 0;
	m_finishedGame = false;
	for(e = 0; e <3; e++)
	{
		for(u = 0; u < 40; u++)
		{
			for(i = 0; i < 128; i++)
			{
				m_tile[e][u][i] = NULL;
			}
		}
	}
	m_imageWall.loadFromFile("ressource/wall.jpg");
	m_spriteWall.setTexture(m_imageWall);
	m_spriteWall.setPosition(0, 0 - m_spriteWall.getGlobalBounds().height * 0.33);
	m_bufferDead.loadFromFile("ressource/explosion.wav");
	m_soundDead.setBuffer(m_bufferDead);
}

bool Level::entityCollisionTile(const sf::Vector2f position, const int u, const int direction)
{
    if(direction == 1)
    {
        int x = (position.x + 32) / 32;
        int y = (position.y + 31) / 32;
        if(m_tile[u][y][x - 1] != NULL)
            if(m_tile[u][y][x - 1]->block())
                return true;
    }
    if(direction == 2)
    {
        int x = position.x / 32;
        int y = (position.y + 31) / 32;
        if(m_tile[u][y][x + 1] != NULL)
            if(m_tile[u][y][x + 1]->block())
                return true;
    }
    if(direction == 3)
    {
        int x = (position.x + 16) / 32;
        int y = (position.y + 32) / 32;
        if(m_tile[u][y - 1][x] != NULL)
            if(m_tile[u][y - 1][x]->block())
                return true;
    }
    if(direction == 4)
    {
        int x = (position.x + 16) / 32;
        int y = position.y / 32;
        if(m_tile[u][y + 1][x] != NULL)
            if(m_tile[u][y + 1][x]->block())
                return true;
    }
    return false;
}

bool Level::entityInTile(const sf::Vector2f position, const int u, const std::string nameTile, const sf::Vector2f hitBox)
{
    int x = (position.x + hitBox.x) / 32;
    int y = (position.y + hitBox.y) / 32;
    if(m_tile[u][y][x] != NULL)
        if(m_tile[u][y][x]->getName() == nameTile)
            return true;

    return false;
}

void Level::addBall(const sf::Vector2f position, const float moveX, const float moveY)
{
    unsigned int u;
    for(u = 0; u < m_ball.size(); u++)
    {
        if(m_ball[u]->getDead())
        {
            m_ball[u]->init(position, moveX, moveY);
            return;
        }
    }
    m_ball.push_back(new Ball);
    m_ball[u]->init(position, moveX, moveY);
}

bool Level::getFinishLevel() const
{
    return m_finishedGame;
}

void Level::loadLevel(std::string chemin, Player *player)
{
	sf::Image image;
	std::ostringstream oss;
	m_currentLevel++;
	oss << m_currentLevel;
	chemin += oss.str();
	chemin += ".png";
	if(!image.loadFromFile(chemin))
        m_finishedGame = true;
	m_width = image.getSize().x;
	m_height = image.getSize().y;
	m_mob.clear();
	m_ball.clear();
	int y;
	int x;
	int u;
	int px=0;
	int py=0;
	m_numberMob = 0;
    player->modifyEnergy(10);

	for(u = 0; u <3; u++)
	{
		for(y = 0; y < 40; y++)
		{
			for(x = 0; x < 128; x++)
			{
				m_tile[u][y][x] = NULL;
			}
		}
	}

	for(y = 0; y < m_height; y++)
	{
		for(x = 0; x < m_width; x++)
		{
			if(image.getPixel(x, y) == sf::Color::Color(255, 112, 255))
			{
				m_tile[1][y][x] = new FleshTile;
				m_tile[1][y][x]->init(sf::Vector2f(px, py), m_imageManager, this);
			}
			else if(image.getPixel(x, y) == sf::Color::Color(127, 0, 0))
			{
			    m_tile[0][y][x] = new LadderTile;
			    m_tile[0][y][x]->init(sf::Vector2f(px, py), m_imageManager, this);
			}
			else if(image.getPixel(x, y) == sf::Color::Color(255, 216, 0))
			{
			    m_tile[0][y][x] = new PortalTile;
			    m_tile[0][y][x]->init(sf::Vector2f(px, py), m_imageManager, this);
			}
			else if(image.getPixel(x ,y) == sf::Color::Color(255, 255, 255))
			{
			    m_tile[0][y][x] = new RegenTile;
			    m_tile[0][y][x]->init(sf::Vector2f(px, py), m_imageManager, this);
			}
			else if(image.getPixel(x, y) == sf::Color::Color(0, 255, 33))
			{
			    m_tile[1][y][x] = new InfectedFleshTile;
			    m_tile[1][y][x]->init(sf::Vector2f(px, py), m_imageManager, this);
			}
			else if(image.getPixel(x, y) == sf::Color::Color(128, 128, 128))
			{
                m_mob.push_back(new PikeMob);
                m_mob[m_numberMob]->init(sf::Vector2f(px, py), m_imageManager);
                m_numberMob++;
			}
			else if(image.getPixel(x, y) == sf::Color::Color(0, 127, 14))
			{
                m_mob.push_back(new BacteriaMob);
                m_mob[m_numberMob]->init(sf::Vector2f(px, py), m_imageManager);
                m_numberMob++;
			}
			else if(image.getPixel(x, y) == sf::Color::Color(0, 38, 255))
			{
			    player->setPosition(sf::Vector2f(px, py));
			}
			px+=32;
		}
		px=0;
		py+=32;
	}
}

void Level::setTile(Tile *tile, const int x, const int y, const int u)
{
    if(m_tile[u][y][x] != NULL)
        delete m_tile[u][y][x];
    m_tile[u][y][x] = tile;
    m_tile[u][y][x]->init(sf::Vector2f(x * 32, y *32), m_imageManager, this);
}

void Level::delMob(Mob *mob)
{
    unsigned int e;
    for(e = 0; e < m_mob.size(); e++)
    {
        if(m_mob[e] == mob)
        {
            delete m_mob[e];
            m_mob[e] = NULL;
            m_soundDead.play();
        }
    }
}

void Level::addMob(Mob *mob, const sf::Vector2f position)
{
    m_mob.push_back(mob);
    m_mob[m_numberMob]->init(position, m_imageManager);
    m_numberMob++;
}

Tile* Level::getTile(int x, int y, const int u)
{
    if(x < 0)
        x = 0;
    if(y < 0)
        y = 0;
    if(x > m_width - 1)
        x = m_width - 1;
    if(y > m_height -1)
        y = m_height -1;

    return m_tile[u][y][x];
}

void Level::majEntity(Player *player)
{
    unsigned int u = 0;
	for(u = 0; u < m_ball.size(); u++)
	{
        m_ball[u]->maj(this, &m_mob);
	}
	for(u = 0; u < m_mob.size(); u++)
	{
        if(m_mob[u] != NULL)
            m_mob[u]->maj(player, this);
	}
}

void Level::render(sf::RenderWindow *app, Player *player)
{
    app->draw(m_spriteWall);
	int u;
	int x;
	int y;
	unsigned int e;
	int xx = (player->getPosition().x + 16) / 32;
	int yy = (player->getPosition().y + 16) / 32;
	for(u = 0; u < 1; u++)
	{
		for(y = yy - 8; y < yy + 8; y++)
		{
		    if(y < 0)
                y = 0;
			for(x = xx - 8; x < xx + 8; x++)
			{
			    if(x < 0)
                    x = 0;
				if(m_tile[u][y][x] != NULL)
				{
					m_tile[u][y][x]->render(app);
					m_tile[u][y][x]->tick(player, this);
				}
			}
		}
	}
	player->render(app);

	for(e = 0; e < m_ball.size(); e++)
	{
        m_ball[e]->render(app);
	}

	for(e = 0; e < m_mob.size(); e++)
	{
	    if(m_mob[e] != NULL)
            m_mob[e]->render(app);
	}

    for(u = 1; u < 3; u++)
	{
		for(y = yy - 8; y < yy + 8; y++)
		{
            if(y < 0)
                y = 0;
			for(x = xx - 8; x < xx + 8; x++)
			{
                if(x < 0)
                    x = 0;
				if(m_tile[u][y][x] != NULL)
				{
					m_tile[u][y][x]->render(app);
					m_tile[u][y][x]->tick(player, this);
				}
			}
		}
	}

}
